package com.dailywork.basepro.stroper;

import lombok.Getter;

import java.math.BigDecimal;

/**
 * @author think
 * @version 2019/10/28
 * @since 数学基础运算
 */
public enum EnumOperation {
    /**
     * 加法运算
     */
    PLUS("+") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.addExact(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.addExact(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.add(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    },
    /**
     * 减法运算
     */
    MINUS("-") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.subtractExact(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.subtractExact(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.subtract(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    },
    /**
     * 乘法运算
     */
    MULTY("*") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.multiplyExact(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.multiplyExact(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.multiply(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    },
    /**
     * 除法运算
     */
    DIV("/") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.floorDiv(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.floorDiv(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.divide(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    },
    MODE("%") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.floorMod(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.floorMod(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            return 0.0;
        }
    },
    MIN("MIN") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.min(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.min(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.min(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    },
    MAX("MAX") {
        @Override
        Integer apply(Integer a, Integer b) {
            return Math.max(a, b);
        }

        @Override
        Long apply(Long a, Long b) {
            return Math.max(a, b);
        }

        @Override
        Double apply(Double a, Double b) {
            BigDecimal bigDecimal1 = new BigDecimal(a);
            BigDecimal bigDecimal2 = new BigDecimal(b);
            return bigDecimal1.max(bigDecimal2).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
    };

    @Getter
    private String symbol;

    EnumOperation(String symbol) {
        this.symbol = symbol;
    }

    abstract Integer apply(Integer a, Integer b);

    abstract Long apply(Long a, Long b);

    abstract Double apply(Double a, Double b);
}
